import { chunk, flat, map } from "./array";

export class Matrix {
  rows = 0;
  cols = 0;
  values = [[]];

  /**
   * @param {Array<Array>} matrix
   */
  constructor(matrix) {
    this.values = matrix;
    this.rows = this.values.length;
    this.cols = this.values[0].length;
  }

  static fromArray(array, rows) {
    const matrix = chunk(array, rows);
    return new Matrix(matrix);
  }

  toArray() {
    return flat(this.values);
  }

  get(i, j) {
    return this.values[i][j];
  }

  getRow(i) {
    return this.values[i];
  }

  getCol(j) {
    return this.values.map(row => row[j]);
  }

  set(i, j, value) {
    this.values[i][j] = value;
  }

  map(func) {
    return new Matrix(this.values.map((row, i) => row.map((v, j) => func(v, i, j))));
  }

  mapRow(func) {
    return new Matrix(this.values.map(func));
  }

  mapCol(func) {
    return new Matrix(map(this.cols, (j) => this.getCol(j)).map(func));
  }

  transpose() {
    return new Matrix(map(this.cols, (j) => this.getCol(j)));
  }

  reverse() {
    return new Matrix(this.values.map(row => row.reverse()));
  }
}